﻿using Mengsk.ProxyDelivery.Domain;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Xml.Linq;

namespace Mengsk.ProxyDelivery.Service
{
    public class AddressService
    {
        public static readonly string DIR = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;
        public static readonly string DIR_CONFIG = DIR + "\\Config\\";

        private static readonly string[] D_CITY = new string[] { "北京", "上海", "天津", "重庆" };
        private static String[] D_PROVINCE = new string[] { "宁夏", "广西", "内蒙古", "西藏", "新疆", "香港", "澳门", "台湾" };
        private static string[] RemoveWords = new string[] { "自治州", "自治县", "土家族", "苗族", "藏族", "蒙古", "蒙古族", "柯尔克孜自", "哈萨克", "黎族", "彝族", "傣族", "景颇族", "傈僳族", "回族", "壮族", "哈尼族", "白族", "侗族", "地区", "羌族", "群岛", "岛", "哈萨克", "哈尼族", "布依族", "地区" };

        const string FILENAME = "Address.xml";
        private static readonly Address instance = new Address();
        public static Address Address { get { return instance; } }

        static AddressService()
        {
            String path = System.IO.Path.Combine(DIR_CONFIG, FILENAME);

            if (File.Exists(path) == false)
            {
                throw new Exception("地址配置文件不存在:" + path);
            }

            try
            {
                XDocument xDoc = XDocument.Load(path);

                foreach (var country in xDoc.Root.Elements("Country"))
                {
                    Country c = new Country { Name = country.Attribute("Name").Value, Code = country.Attribute("Code").Value };
                    Address.Contries.Add(c);

                    foreach (var state in country.Elements("State"))
                    {
                        State s = new State { Name = state.Attribute("Name").Value, Code = state.Attribute("Code").Value };
                        c.States.Add(s);
                        foreach (var city in state.Elements("City"))
                        {
                            City cc = new City { Name = city.Attribute("Name").Value, Code = city.Attribute("Code").Value };
                            s.Cities.Add(cc);
                            foreach (var region in city.Elements("Region"))
                            {
                                Region r = new Region { Name = region.Attribute("Name").Value, Code = region.Attribute("Code").Value };
                                cc.Regions.Add(r);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("加载地址文件失败:" + ex.Message);
            }
        }


        /// <summary>
        /// 删除前面的字符如四川省成都市，四川，则返回 省成都市
        /// </summary>
        /// <param name="value"></param>
        /// <param name="trimValue"></param>
        /// <returns></returns>
        private static string TrimStart(String value, string trimValue, int minCount = 2)
        {
            for (int i = trimValue.Length; i >= 1 && i >= minCount; i--)
            {
                string subTrimValue = trimValue.Substring(0, i);
                if (value.StartsWith(subTrimValue))
                {
                    value = value.Substring(subTrimValue.Length).Trim();
                    return value.Trim();
                }
            }

            return value.Trim();
        }

        public static string GetCityShortName(string city)
        {
            //检查自治区
            string d_city = D_CITY.FirstOrDefault(c => c.StartsWith(city));
            if (string.IsNullOrWhiteSpace(d_city) == false)
            {
                return d_city;
            }

            string s = city.TrimEnd('市', '县', '盟', '区').Trim();
            foreach (string removeWord in RemoveWords)
            {
                s = s.Replace(removeWord, "");
            }
            return s;
        }


        /// <summary>
        /// 解析省
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static State ParseProvince(string address)
        {
            address = address.Replace(",", "").Replace("。", "").Trim();

            //直辖市
            string dCity = D_CITY.FirstOrDefault(obj => address.StartsWith(obj));
            if (dCity != null)
            {
                return AddressService.Address.Contries[0].States.FirstOrDefault(obj => obj.Name.StartsWith(dCity));
            }

            //地址库中的省进行匹配
            State state = AddressService.Address.Contries[0].States.FirstOrDefault(s => address.StartsWith(s.Name.Trim('省')));
            if (state != null)
            {
                return state;
            }

            //检查自治区
            string sName = D_PROVINCE.FirstOrDefault(s => address.StartsWith(s));
            if (sName != null)
            {
                state = AddressService.Address.Contries[0].States.FirstOrDefault(obj => obj.Name.StartsWith(sName));
            }
            if (state != null)
            {
                return state;
            }

            //如果没有输入省，则检查是否有市
            foreach (var ss in AddressService.Address.Contries[0].States)
            {
                //生成市的短名称
                String[] cityShortNames = ss.Cities.Select(c =>
                {
                    string s = c.Name.TrimEnd('市', '县', '盟').Trim();
                    foreach (string removeWord in RemoveWords)
                    {
                        s = s.Replace(removeWord, "");
                    }
                    return s;
                }).ToArray();
                string cityName = cityShortNames.FirstOrDefault(c => address.StartsWith(c));
                if (string.IsNullOrWhiteSpace(cityName) == false)
                {
                    return ss;
                }
            }

            return null;
        }

        /// <summary>
        /// 解析市
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static City ParseCity(string address)
        {
            address = address.Replace(",", "").Replace("。", "").Trim();
            State state = ParseProvince(address);
            string ad = null;
            if (state == null)
            {
                return null;
            }
            //检查直辖市
            var dcity = D_CITY.FirstOrDefault(obj => address.StartsWith(obj));
            if (string.IsNullOrWhiteSpace(dcity) == false)
            {
                if (state.Cities.Count < 1)
                {
                    return null;
                }
                return state.Cities[0];
            }

            ad = TrimStart(address, state.Name).TrimStart('省').Trim();

            //处理市,全字匹配
            var city = state.Cities.FirstOrDefault(c => ad.StartsWith(c.Name.Trim('市')));
            if (city != null)
            {
                return city;
            }

            //将市名称中的市，县，自治州，民族等删除掉进行匹配
            String[] cityShortNames = state.Cities.Select(c =>
            {
                string s = c.Name.TrimEnd('市', '县', '盟');
                foreach (string removeWord in RemoveWords)
                {
                    s = s.Replace(removeWord, "");
                }
                return s;
            }).ToArray();

            string cityName = cityShortNames.FirstOrDefault(c => ad.StartsWith(c));
            if (String.IsNullOrWhiteSpace(cityName) == false)
            {
                city = state.Cities.FirstOrDefault(c => c.Name.StartsWith(cityName));
                if (city != null)
                {
                    return city;
                }
            }


            //如果没有输入省，则检查是否有市
            foreach (var ss in AddressService.Address.Contries[0].States)
            {
                //生成市的短名称
                String[] cityShortNamesAll = ss.Cities.Select(c =>
                {
                    string s = c.Name.TrimEnd('市', '县', '盟').Trim();
                    foreach (string removeWord in RemoveWords)
                    {
                        s = s.Replace(removeWord, "");
                    }
                    return s;
                }).ToArray();
                string cityNameShort = cityShortNamesAll.FirstOrDefault(c => address.StartsWith(c));
                if (string.IsNullOrWhiteSpace(cityNameShort) == false)
                {
                    return ss.Cities.FirstOrDefault(obj => obj.Name.StartsWith(cityNameShort));
                }
            }

            return null;
        }


        /// <summary>
        /// 解析区或者县或者地级市
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static Region ParseRegion(string address)
        {
            address = address.Replace(",", "").Replace("。", "").Trim();
            State s = ParseProvince(address);
            if (s == null)
            {
                return null;
            }

            City c = ParseCity(address);
            if (c == null)
            {
                return null;
            }

            //删除前面的省市
            string ad = TrimStart(address, s.Name).TrimStart('省').Trim();
            ad = TrimStart(ad, c.Name).TrimStart('市').Trim();

            //查找区
            var region = c.Regions.FirstOrDefault(r => ad.StartsWith(r.Name.TrimEnd('县', '市', '区', '镇')));
            if (region != null)
            {
                return region;
            }
            ad = ad.Replace(" ", "").Trim();
            region = c.Regions.FirstOrDefault(r => ad.StartsWith(r.Name.TrimEnd('县', '市', '区', '镇')));

            if (region != null)
            {
                return region;
            }

            int townIndex = ad.IndexOf("镇");

            if (townIndex > 0)
            {
                return new Region { Code = "", Name = ad.Substring(0, townIndex + 1) };
            }

            return null;
        }
    }
}
